#include "http_link_manager.h"
#include "escal.h"
#include <QTextStream>
#include <QByteArray>

HttpLinkManager::HttpLinkManager(FileManager *fileManager,
	const QUrl &url, QObject *parent)
	:BaseLinkManager(parent)
{
	this->url = url;
	this->fileManager = fileManager;
	this->pieceIndex = 0;
	this->offset = 0;
	reconnect = false;
	gotPiece = false;
	error = false;
	quit = false;
	// connect(this, SIGNAL(linkQuit()), 
	//	this, SLOT(stopDownload()));
	connect(&http, SIGNAL(responseHeaderReceived(
		const QHttpResponseHeader &)),
		this, SLOT(readResponseHeader(
		const QHttpResponseHeader &)));
	connect(&http, SIGNAL(readyRead(const QHttpResponseHeader &)), 
		this, SLOT(readResponseData( const QHttpResponseHeader &)));
	connect(&http, SIGNAL(done( bool)),
		this, SLOT(httpRequestDone( bool)));
	connect(&http, SIGNAL(dataReadProgress(int, int)),
		this, SLOT(updateDataReadProgress(int, int)));
}

HttpLinkManager::~HttpLinkManager(){
	qDebug() << "HttpLinkManager::~HttpLinkManager";
	stop();
	wait();
	qDebug() << "HttpLinkManager::~HttpLinkManager 3";
	cleanUp();
	qDebug() << "HttpLinkManager::~HttpLinkManager 2";
}

void HttpLinkManager::cleanUp(){
	if(gotPiece){
		fileManager->releasePiece(pieceIndex);
		gotPiece=false;
	}
}

void HttpLinkManager::stop(){
	qDebug() << "HttpLinkManager::stop()";
	quit = true;
	http.abort();
	exit(0);
	qDebug() << "HttpLinkManager::stop() 2";
}

void HttpLinkManager::run(){
	startDownload();
	exec();
}

void HttpLinkManager::startDownload(){
	qDebug() << "HttpLinkManager::startDownload()";
	reconnect = false;
	error = false;
	quit = false;
	if(!fileManager->isNew()){
		if(!gotPiece && ((pieceIndex = fileManager->getPiece()) <0)){
			 error = true;
			 //stopDownload();
			 //http.abort();
			 quit = true;
			 //httpRequestDone(true);
			 emit linkQuited(this, true);
			 exit(0);
			 return;
		}
		else{
			 gotPiece = true;
		}
	}
	QHttp::ConnectionMode mode = 
		url.scheme().toLower() == "https" ? 
		QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp;
	http.setHost(url.host(), mode, url.port() == -1 ? 0 : url.port());
	QByteArray urlPath = QUrl::toPercentEncoding(
			url.path(), "!$&'()*+,;=:@/");

	QHttpRequestHeader header("GET", urlPath);
	header.setValue("Host", url.host());
	if(gotPiece && (pieceIndex != 0 || offset != 0)) {
		header.setValue("Range", QString("bytes=%1-")
				.arg(pieceIndex * PieceSize + offset));
	}
	
	httpGetId = http.request(header);
}

void HttpLinkManager::stopDownload(){
	cleanUp();
	reconnect = false;
	quit = true;
	http.abort();
	emit linkQuited(this, error);
	// quit();
}

void HttpLinkManager::readResponseHeader(
		const QHttpResponseHeader &responseHeader)
{
	// debug 
	QString str;
	foreach(str, responseHeader.keys()){
		qDebug() << str << " " << responseHeader.value(str);
	}
	qDebug() << "status: " << responseHeader.statusCode();
	switch (responseHeader.statusCode()) {
	case 200:				   // Ok
	case 206:
	case 301:				   // Moved Permanently
	//case 302:				   // Found
	case 303:				   // See Other
	case 307:				   // Temporary Redirect
		// these are not error conditions
		break;
	default:
		error = true;
		http.abort();
		return;
		//stopDownload();
	}
	if(fileManager->isNew()){
		qint64 fileSize = responseHeader.value("Content-Length").toUInt();
	if(fileSize==0){
		reconnect = false;
		error = true;
		http.abort();
		return;
		//stopDownload();

	}
		bool acceptRange = ( responseHeader.value("Accept-Ranges") == "bytes" ?
		true : false);
		fileManager->initNewFile(fileSize, acceptRange);
	}
	if(!gotPiece){
		pieceIndex = fileManager->getPiece();
		if(pieceIndex < 0){
			error = true;
			http.abort();
			return;
			//stopDownload();
		}
		gotPiece = true;
		if(pieceIndex != 0){
			reconnect = true;
			http.abort();
			return;
		}
	}
}

void HttpLinkManager::httpRequestDone(bool error){
	qDebug() << "HttpLinkManager::httpRequestDone()";
	if(quit || !reconnect){
		QThread::exit(0);
		//emit linkQuit();
		emit linkQuited(this, this->error);
	}
	else{
		reconnect = false;
		startDownload();
	}
}

void HttpLinkManager::readResponseData( const QHttpResponseHeader & responseHeader){
	QByteArray data = http.readAll();
	if((reconnect = fileManager->write(pieceIndex, offset, data))){
		offset = 0;
		pieceIndex = fileManager->getPiece();
		if(pieceIndex <0){
			reconnect = false;
			gotPiece = false;
		}
		http.abort();
	}
}


void HttpLinkManager::updateDataReadProgress(int bytesRead, int totalBytes){

}

